/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.server;

import nfse.gui.config.*;

import nfse.NetFSE;
import nfse.NetFSEUtil;
import nfse.gui.query.*;
import java.io.*;
import java.sql.*;
import java.util.*;

import javax.net.SocketFactory;
import java.net.Socket;

import nfse.NetFSERecord;
import nfse.DataServer;

public class ConfigServiceImpl extends NetFSEServiceServlet implements
		ConfigService {

	public ConfigServiceImpl() {
		super();

	}

	public void deleteSyslogConfig(SyslogConfig config) {
		try {
			String sql = "delete from syslog_agent_conf where sensor="
					+ config.sensor + "";
			Statement s = createMetadataStatement();
			// System.out.println(sql);
			s.execute(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void deleteNetFlowConfig(NetFlowConfig config) {
		try {
			String sql = "delete from netflow_agent_conf where sensor="
					+ config.sensor + "";
			Statement s = createMetadataStatement();
			s.execute(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void deleteSensor(int sensorID) {
		try {
			String sql = "update sensors set tool_id = -1 where id=" + sensorID
					+ "";
			Statement s = createMetadataStatement();
			s.execute(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public String syslogAndNetFlowControl(int sensorID, int opType) {
		String message = "";
		try {
			// System.out.println("Sensor: " + sensorID + ", Op: " + opType);
			String userName = getUserName();

			boolean admin = isAdmin(userName);
			if (!admin)
				return "You must be an admin to execute this function.";

			SocketFactory sf = SocketFactory.getDefault();
			Socket socket = sf.createSocket("localhost",
					NetFSE.CONTROL_SERVER_PORT);
			DataOutputStream socketOut = new DataOutputStream(socket
					.getOutputStream());
			DataInputStream socketIn = new DataInputStream(socket
					.getInputStream());

			socketOut.writeInt(sensorID);
			socketOut.writeInt(opType);

			socketIn.readInt();
			socketIn.close();
			socketOut.close();
			socket.close();

			message = "Operation complete.";
		} catch (Exception e) {
			e.printStackTrace();
			message = e.getMessage();
		}
		System.out.println(message);
		return message;
	}

	public SensorInfo[] getSensorInfo() {

		SensorInfo[] results = null;
		try {
			Vector<SensorInfo> temp = new Vector<SensorInfo>();
			String sql = "select a.id as sensor_id, a.name as sensor_name, b.name as type_name, b.id as type_id from sensors a, tools b  where a.tool_id=b.id and tool_id != -1";
			Statement s = createMetadataStatement();
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				SensorInfo info = new SensorInfo();
				info.id = rs.getInt("sensor_id");
				info.sensorName = rs.getString("sensor_name");
				info.typeName = rs.getString("type_name");
				NetFSERecord rec = NetFSE.getTypeClass(rs.getInt("type_id"));
				info.isSyslog = rec.isSyslog();
				temp.addElement(info);
			}
			rs.close();
			s.close();
			results = new SensorInfo[temp.size()];
			for (int i = 0; i < results.length; i++) {
				results[i] = (SensorInfo) temp.elementAt(i);
			}
			return results;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return results;
	}

	public DailyRecordCountInfo getDailyRecordCounts(int numDays) {
		DailyRecordCountInfo result = null;
		try {
			Vector<DailyRecordCount> temp = new Vector<DailyRecordCount>();
			String sql = "select * from Daily_Record_Counts where Entry_Date > date(now()) - interval '"
					+ numDays + " days'";
			Statement s = createMetadataStatement();
			ResultSet rs = s.executeQuery(sql);
			long secondsNotCollecting = 0;
			long recordsDropped = 0;
			long recordsProcessed = 0;
			while (rs.next()) {
				DailyRecordCount drc = new DailyRecordCount();
				drc.date = rs.getString("Entry_Date");
				drc.recordCount = rs.getLong("records_processed");
				recordsProcessed += drc.recordCount;
				drc.exceededCount = rs.getLong("Records_Over");
				recordsDropped += drc.exceededCount;
				Timestamp ts = rs.getTimestamp("Threshold_TS");
				if (ts == null)
					drc.exceededTS = "-";
				else {
					drc.exceededTS = ts.toString();
					GregorianCalendar cal = new GregorianCalendar();
					cal.setTimeInMillis(ts.getTime());
					cal.set(Calendar.HOUR_OF_DAY, 0);
					cal.set(Calendar.MINUTE, 0);
					cal.set(Calendar.SECOND, 0);
					cal.set(Calendar.MILLISECOND, 0);
					cal.add(Calendar.DAY_OF_MONTH, 1);

					long ts2 = cal.getTimeInMillis();
					int sec = (int) ((ts2 - ts.getTime()) / (long) 1000);
					secondsNotCollecting += sec;

				}

				temp.addElement(drc);
			}
			rs.close();

			int hours = (int) (secondsNotCollecting / 3600);
			int min = (int) ((secondsNotCollecting - hours * 3600) / 60);
			if (min < 0)
				min = 0;

			result = new DailyRecordCountInfo();
			result.recordsDropped = recordsDropped;
			result.totalRecords = recordsProcessed;
			result.numDays = numDays;
			result.recordThreshold = DataServer.RECORD_THRESHOLD;
			result.timeNotCollecting = hours + " ";
			if (hours != 1)
				result.timeNotCollecting += "hrs, ";
			else
				result.timeNotCollecting += "hr, ";
			result.timeNotCollecting += min + " ";
			if (hours != 1)
				result.timeNotCollecting += "mins";
			else
				result.timeNotCollecting += "min";

			s.close();

			result.dailyRecordCounts = new DailyRecordCount[temp.size()];
			for (int i = 0; i < result.dailyRecordCounts.length; i++) {
				result.dailyRecordCounts[i] = temp.elementAt(i);
			}

			// return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public SyslogConfig[] getSyslogConfigs() {
		SyslogConfig[] results = null;
		try {
			Vector<SyslogConfig> temp = new Vector<SyslogConfig>();
			String sql = "select * from syslog_agent_conf a, sensors b where a.sensor=b.id ";
			Statement s = createMetadataStatement();
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				int sensor = rs.getInt("sensor");
				String sensorName = rs.getString("name");
				String ip = rs.getString("ip");
				if (ip == null)
					ip = "";

				String filePath = rs.getString("file_path");
				String keyword = rs.getString("keyword");
				SyslogConfig st = new SyslogConfig();
				st.filePath = filePath;
				st.ip = ip;
				st.keyword = keyword;
				st.sensor = sensor;
				st.sensorName = sensorName;
				temp.addElement(st);
			}
			rs.close();
			s.close();
			results = new SyslogConfig[temp.size()];
			for (int i = 0; i < results.length; i++) {
				results[i] = (SyslogConfig) temp.elementAt(i);
			}
			return results;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return results;
	}

	public NetFlowConfig[] getNetFlowConfigs() {
		NetFlowConfig[] results = null;
		try {
			Vector<NetFlowConfig> temp = new Vector<NetFlowConfig>();
			String sql = "select * from netflow_agent_conf a, sensors b where a.sensor=b.id ";
			Statement s = createMetadataStatement();
			ResultSet rs = s.executeQuery(sql);
			while (rs.next()) {
				int sensor = rs.getInt("sensor");
				int port = rs.getInt("port");
				String sensorName = rs.getString("name");
				NetFlowConfig st = new NetFlowConfig();
				st.sensor = sensor;
				st.sensorName = sensorName;
				st.port = port;
				temp.addElement(st);
			}
			rs.close();
			s.close();
			results = new NetFlowConfig[temp.size()];
			for (int i = 0; i < results.length; i++) {
				results[i] = (NetFlowConfig) temp.elementAt(i);
			}
			return results;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return results;
	}

	public String addSensor(SensorInfo info) {
		try {
			Statement statement = createMetadataStatement();

			String sql = "select * from Sensors where Name='" + info.sensorName
					+ "'";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				int typeID = rs.getInt("Tool_ID");
				rs.close();
				statement.close();
				if (typeID == -1)
					return "Request failed: a sensor named '" + info.sensorName
							+ "' previously existed. Chose another name.";
				else
					return "Request failed: a sensor named '" + info.sensorName
							+ "' already existed. Chose another name.";
			}
			rs.close();

			sql = "insert into Sensors values (nextval('sensor_id_seq'),"
					+ info.type + ",'" + info.sensorName + "')";
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Add Sensor request completed.";
	}

	public String addNetFlowConfig(NetFlowConfig config) {
		try {
			Statement statement = createMetadataStatement();

			String sql = "select * from netflow_agent_conf where sensor="
					+ config.sensor + "";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: a configuration for the sensor '"
						+ NetFSE.getSensorInfo(config.sensor).getName()
						+ "' already exists.";
			}
			rs.close();

			sql = "select * from netflow_agent_conf where port=" + config.port
					+ "";
			rs = statement.executeQuery(sql);
			if (rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: an existing configuration is already using port "
						+ config.port + ".";
			}
			rs.close();

			sql = "insert into netflow_agent_conf values (" + config.sensor
					+ "," + config.port + ")";
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Add NetFlow agent configuration request completed.";
	}

	public String addSyslogConfig(SyslogConfig config) {
		try {
			Statement statement = createMetadataStatement();

			String sql = "select * from syslog_agent_conf where sensor="
					+ config.sensor + "";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: a configuration already exists for sensor '"
						+ NetFSE.getSensorInfo(config.sensor).getName() + "'";

			}
			rs.close();

			File f = new File(config.filePath);
			if (!f.exists()) {
				statement.close();
				return "Add Syslog Configuration request failed because the specified file does not exist.";
			}

			String ipVal = "null";
			if (config.ip.length() > 0) {
				ipVal = "'" + config.ip + "'";
			}

			sql = "insert into syslog_agent_conf values (" + config.sensor
					+ ",'" + config.filePath + "','" + config.keyword + "',"
					+ ipVal + ")";
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Add Syslog Configuration request completed.";
	}

	public String editSyslogConfig(SyslogConfig config) {
		try {
			deleteSyslogConfig(config);
			addSyslogConfig(config);
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Edit syslog configuration request completed.";
	}

	public String editNetFlowConfig(NetFlowConfig config) {
		try {
			deleteNetFlowConfig(config);
			addNetFlowConfig(config);
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Edit NetFlow configuration request completed.";
	}

	public String addCriticalServer(CriticalServerEntry server) {
		try {
			Statement statement = createMetadataStatement();

			String sql = "select * from Critical_Servers where Server_IP='"
					+ server.ip + "'";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: a critical server entry already exists for "
						+ server.ip + "";
			}
			rs.close();

			int asSrc = 0;
			if (server.asSrc)
				asSrc = 1;
			int asDst = 0;
			if (server.asDst)
				asDst = 1;

			sql = "insert into Critical_Servers values ('" + server.ip
					+ "','', " + asSrc + "," + asDst + ", '"
					+ NetFSEUtil.convertToHex(server.note) + "')";
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Add Critical Server request completed.";
	}

	public String addUser(UserInfo userInfo) {
		try {

			String hashHex = NetFSEUtil.encodePassword(userInfo.password);

			String userName = getUserName();

			boolean admin = isAdmin(userName);
			if (!admin)
				return "You must be an admin to execute this function.";

			Statement statement = createMetadataStatement();

			int adminVal = 0;
			if (userInfo.admin)
				adminVal = 1;
			String sql = "insert into Users values (nextval('user_id_seq'),'"
					+ userInfo.userName + "','" + hashHex + "','"
					+ userInfo.realName + "'," + adminVal + ",0)";
			statement.execute(sql);
			statement.close();
			return "Added user '" + userInfo.userName + "'.";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "Add user failed.";
	}

	public CriticalServerEntry[] getCriticalServers() {
		try {
			Vector<CriticalServerEntry> temp = new Vector<CriticalServerEntry>();

			Statement statement = createMetadataStatement();
			ResultSet rs = statement
					.executeQuery("select * from Critical_Servers");
			while (rs.next()) {
				CriticalServerEntry cse = new CriticalServerEntry();
				cse.ip = rs.getString("Server_IP");
				int asSrc = rs.getInt("As_Src");
				if (asSrc == 1) {
					cse.asSrc = true;
				} else {
					cse.asSrc = false;
				}
				int asDst = rs.getInt("As_Dst");
				if (asDst == 1) {
					cse.asDst = true;
				} else {
					cse.asDst = false;
				}
				String note = rs.getString("Note");
				if (note == null)
					note = "";
				cse.note = NetFSEUtil.convertFromHex(note);
				temp.addElement(cse);
			}
			rs.close();
			statement.close();

			CriticalServerEntry[] results = new CriticalServerEntry[temp.size()];
			for (int i = 0; i < results.length; i++) {
				results[i] = temp.elementAt(i);
			}
			return results;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new CriticalServerEntry[0];
	}

	public EmailReportConfigs getEmailReportConfigs() {
		try {

			Statement statement = createMetadataStatement();
			EmailReportConfigs temp = new EmailReportConfigs();

			String sql = "select * from Email_Report_Config ";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				temp.address = rs.getString("Email_Address");
				temp.frequency = rs.getInt("Frequency");
				temp.server = rs.getString("SMTP_Server");
				if (temp.server == null)
					temp.server = "";
			} else {

			}
			rs.close();

			statement.close();
			return temp;
		} catch (Exception E) {
			E.printStackTrace();
		}
		return null;
	}

	public QueryInfo getQueryInfo(String queryID) {
		try {
			QueryInfo info = new QueryInfo();
			Statement statement = null;
			try {
				statement = resultConnection.createStatement();
			} catch (Exception e) {
				e.printStackTrace();
				Class.forName("com.mysql.jdbc.Driver").newInstance();
				resultConnection = DriverManager.getConnection("jdbc:mysql://"
						+ NetFSE.RESULT_DB_HOST + ":"+ NetFSE.RESULT_DB_PORT + "/"
						+ NetFSE.RESULT_DB_DATABASE, NetFSE.RESULT_DB_USER,
						NetFSE.RESULT_DB_PASSWORD);
				statement = resultConnection.createStatement();
			}

			String sql = "select Note from Queries where Query_ID='" + queryID
					+ "'";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				info.note = NetFSEUtil.convertFromHex(rs.getString("Note"));
				if (info.note == null)
					info.note = "";
			}
			rs.close();

			Vector<Integer> types = new Vector<Integer>();
			sql = "select * from Query_Types where Query_ID='" + queryID + "'";
			rs = statement.executeQuery(sql);
			while (rs.next()) {
				types.addElement(rs.getInt("type_id"));
			}
			rs.close();

			info.types = new int[types.size()];
			for (int i = 0; i < info.types.length; i++)
				info.types[i] = ((Integer) types.elementAt(i));

			statement.close();
			return info;
			// c.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
		return null;
	}

	public TypeInfo getTypeInfo() {
		TypeInfo typeInfo = new TypeInfo();
		typeInfo.types = NetFSE.getTypes();
		typeInfo.typeNames = new String[typeInfo.types.length];
		typeInfo.schemas = new String[typeInfo.types.length];
		for (int i = 0; i < typeInfo.types.length; i++) {
			typeInfo.typeNames[i] = NetFSE.getTypeClass(typeInfo.types[i])
					.getDisplayTypeName();
			typeInfo.schemas[i] = NetFSE.getSchema(typeInfo.types[i]);
		}
		return typeInfo;
	}

	public UserInfo getUserInfo() {
		UserInfo info = null;
		try {

			Statement statement = createMetadataStatement();

			String userName = getUserName();

			String sql = "select * from Users where User_Name='" + userName
					+ "'";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				info = new UserInfo();
				info.userID = rs.getInt("ID");
				info.userName = rs.getString("User_Name");
				info.realName = rs.getString("Real_Name");
				int admin = rs.getInt("Admin");
				if (admin != 0)
					info.admin = true;
				else
					info.admin = false;
			} else {
				info = new UserInfo();
				info.admin = true;
				info.userName = "";
			}
			rs.close();

			statement.close();

		} catch (Exception E) {
			E.printStackTrace();
		}
		return info;
	}

	public UserInfo[] getUsers() {
		try {
			Statement statement = createMetadataStatement();
			Vector<UserInfo> temp = new Vector<UserInfo>();
			ResultSet rs = statement.executeQuery("select * from Users ");
			while (rs.next()) {
				UserInfo user = new UserInfo();
				user.userName = rs.getString("User_Name");
				user.realName = rs.getString("Real_Name");
				if (rs.getInt("Admin") != 0) {
					user.admin = true;
				} else
					user.admin = false;
				temp.addElement(user);
			}
			rs.close();
			statement.close();

			UserInfo[] users = new UserInfo[temp.size()];
			for (int i = 0; i < users.length; i++) {
				users[i] = temp.elementAt(i);
			}

			return users;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public boolean isAdmin(String user) {
		try {
			if (user.equals(""))
				return true;

			Statement statement = createMetadataStatement();
			boolean admin = false;
			String userName = getUserName();

			ResultSet rs = statement
					.executeQuery("select * from Users where User_Name='"
							+ userName + "'");
			if (rs.next()) {
				if (rs.getInt("Admin") != 0) {
					admin = true;
				}
			}
			rs.close();
			statement.close();
			return admin;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public String removeCriticalServer(String ip) {
		try {
			Statement statement = createMetadataStatement();
			String sql = "select * from Critical_Servers where Server_IP='"
					+ ip + "'";
			ResultSet rs = statement.executeQuery(sql);
			if (!rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: no such entry in critical server list ('"
						+ ip + "')";
			}
			rs.close();

			sql = "delete from Critical_Servers where Server_IP='" + ip + "'";
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Remove Critical Server request completed.";
	}

	public void setNote(String queryID, String note) {
		try {

			Statement s1 = createResultStatement();

			if (note == null)
				note = "";
			if (note.length() > 0) {
				try {
					NetFSEUtil.convertFromHex(note);
				} catch (Exception e) {
					note = NetFSEUtil.convertToHex(note);
				}
			}

			String sql = "update Queries set Note='" + note
					+ "' where Query_ID='" + queryID + "'";
			s1.execute(sql);

			s1.close();
			// c.close();
		} catch (Exception E) {
			E.printStackTrace();
		}
	}

	public String setPasswordAdmin(String user, String password) {
		try {

			String userName = getUserName();
			boolean admin = isAdmin(userName);
			if (!admin)
				return "You must be an admin to execute this function.";

			Statement statement = createMetadataStatement();

			String sql = "update Users set Password='" + NetFSEUtil.encodePassword(password)
					+ "' where User_Name='" + user + "'";
			statement.execute(sql);
			statement.close();
			return "Password update complete.";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "Password update failed";
	}

	public String setPasswordUser(String oldPassword, String newPassword) {
		try {

			String userName = getUserName();

			Statement statement = createMetadataStatement();

			String sql = "select * from Users where User_Name='" + userName
					+ "'";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				String password = rs.getString("Password");
				if (!password.equals(oldPassword)) {
					rs.close();
					statement.close();
					return "The password specified does not match the current password.";
				}
			} else {
				rs.close();
				statement.close();
				return "The specified user does not exist";
			}
			rs.close();

			sql = "update Users set Password='" + NetFSEUtil.encodePassword(newPassword)
					+ "' where User_Name='" + userName + "'";
			statement.execute(sql);
			statement.close();
			return "Password updated.";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "Password update failed";
	}

	public String updateCriticalServer(String ip, CriticalServerEntry server) {
		try {

			String userName = getUserName();

			boolean admin = isAdmin(userName);
			if (!admin)
				return "You must be an admin to execute this function.";

			Statement statement = createMetadataStatement();

			String sql = "select * from Critical_Servers where Server_IP='"
					+ ip + "'";
			ResultSet rs = statement.executeQuery(sql);
			if (!rs.next()) {
				rs.close();
				statement.close();
				return "Request failed: no such entry in critical server list ('"
						+ ip + "')";
			}
			rs.close();

			int asSrc = 0;
			if (server.asSrc)
				asSrc = 1;
			int asDst = 0;
			if (server.asDst)
				asDst = 1;

			sql = "update Critical_Servers set Server_IP='" + server.ip
					+ "', As_Src=" + asSrc + ", As_Dst=" + asDst + ", Note='"
					+ NetFSEUtil.convertToHex(server.note)
					+ "' where Server_IP='" + ip + "'";
			// System.out.println(sql);
			statement.execute(sql);

			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Update Critical Server request completed.";
	}

	public String updateEmailReportConfigs(EmailReportConfigs configs) {
		try {

			String userName = getUserName();

			boolean admin = isAdmin(userName);
			if (!admin)
				return "You must be an admin to execute this function.";

			Statement statement = createMetadataStatement();

			int last = 0;
			String sql = "select * from Email_Report_Config";
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				last = rs.getInt("Last");
			}

			sql = "delete from Email_Report_Config";
			statement.execute(sql);

			sql = "insert into Email_Report_Config values ('" + configs.address
					+ "'," + configs.frequency + ",'" + configs.server + "',"
					+ last + "," + configs.port + ")";
			statement.execute(sql);
			statement.close();
		} catch (Exception E) {
			E.printStackTrace();
			return "Request failed: " + E.getMessage();
		}
		return "Email reports configuration change completed.";
	}

	public String updateUser(String userName, UserInfo userInfo) {
		try {

			String user = getUserName();

			boolean admin = isAdmin(user);
			if (!admin)
				return "You must be an admin to execute this function.";

			Statement statement = createMetadataStatement();

			// Check that if the user name is changing that it is unique
			if (!userInfo.userName.equals(userName)) {
				String sql = "select * from Users where User_Name='"
						+ userInfo.userName + "'";
				ResultSet rs = statement.executeQuery(sql);
				if (rs.next()) {
					// A user exists with this user name, return an error
					rs.close();
					statement.close();
					return "Cannot change the user name from '" + userName
							+ "' to '" + userInfo.userName
							+ "' because a user with that name already exists.";
				} else {
					// It is OK to change to this user name
					rs.close();
				}
			}

			int adminVal = 0;
			if (userInfo.admin)
				adminVal = 1;
			String sql = "update Users set User_Name='" + userInfo.userName
					+ "', Real_Name='" + userInfo.realName + "', Admin="
					+ adminVal + " where User_Name='" + userName + "'";
			statement.execute(sql);
			if (userInfo.password.length() > 0) {
				sql = "update Users set Password='" + NetFSEUtil.encodePassword(userInfo.password)
						+ "' where User_Name='" + userName + "'";
				statement.execute(sql);
			}

			statement.close();

			if (!userInfo.userName.equals(userName)) {
				// If the username has changed, update the results database
				statement = createResultStatement();

				sql = "update Queries set User_ID='" + userInfo.userName
						+ "' where User_ID='" + userName + "'";
				statement.execute(sql);
				sql = "update Query_Options set User_ID='" + userInfo.userName
						+ "' where User_ID='" + userName + "'";
				statement.execute(sql);
				statement.close();
			}

			return "Updated user '" + userInfo.userName + "'.";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "Update user failed.";
	}
}
